<!doctype html>
<html>
	<head>
		<title> Test PUI style with angular -- autocomplete </title>
		<link rel="stylesheet" href="../jquery-ui/jquery-ui-1.9.2.custom.min.css" />
		<link rel="stylesheet" href="../development/primeui-1.0.css" />
		<link rel="stylesheet" href="../themes/aristo/theme.css" />
	</head>

	<body ng-controller="MainCtrl">

	<h2>Basic</h2>
	<input type="text" ng-model="aa" 
		ng-disabled="ctrl.isGray"
		data-pui-textfield="" data-pui-autocomplete="" data-list="list" />
	<br />
	{{aa}}
	<br />

	<input type="text" ng-model="bb" 
		data-pui-textfield="" data-pui-autocomplete="" data-list="list" />
	<br />
	{{bb}}
	<br />

	<input type="text" ng-model="cc" data-pui-autocomplete="" data-multiple="true" data-list="list" />
	<br />
	{{cc}}
	<br />

	<script id="pui-autocomplete-panel-tpl" type="text/x-template">
<div class="pui-autocomplete-panel ui-widget-content ui-corner-all pui-shadow" style="display: none;">
 <ul class="pui-autocomplete-items pui-autocomplete-list ui-widget-content ui-widget ui-corner-all ui-helper-reset">
	<li ng-repeat="one in searchList" data-raw-value="{{one}}" 
		class="pui-autocomplete-item pui-autocomplete-list-item ui-corner-all">{{one|puiAutocompleteMatchedShow}}</li>
 </ul>
</div>
	</script>

	<script type="text/javascript" src="zepto-1.1.3.js"></script>
	<script type="text/javascript" src="angular.js"></script>
	<script type="text/javascript" src="underscore.min.js"></script>
	<script type="text/javascript" src="base.js"></script>
	<script language="javascript">
	var md = angular.module('md', []);

	md.directive('puiTextfield', function(){
		return {
			compile: function(el, attrs){
				el.addClass('pui-inputtext ui-widget ui-state-default ui-corner-all');
				el.on('hover', function(){
					el.toggleClass('ui-state-hover');
				}).on('focus', function(){
					el.addClass('ui-state-focus');
				}).on('blur', function(){
					el.removeClass('ui-state-focus');
				});

				return function(scope, el, attrs){
					attrs.$observe('disabled', function(val){
						el[val ? 'addClass' : 'removeClass']('ui-state-disabled');
					});
				};
			}
		};
	});

	md.service('puiAutocompleteHelper', function(){
		this.zindex = 1000;

		this.setPanelPosition = function(panel, $el, opts){
			var offsetEl = $el;

			var multipleWrapper = $el.closest('.pui-autocomplete-multiple');
			if(multipleWrapper.length)
				offsetEl = multipleWrapper;

			var offset = offsetEl.offset();
			panel.css({
				zindex: this.zindex++, 
				width: offsetEl.width(), 
				height: opts.height + 'px', 
				top: offset.top + offsetEl.height(), 
				left: offset.left
			});
		};

		this.bindPanelEvent = function(panel){
			var hoverClass = 'ui-state-highlight';
			panel.delegate('li', 'mouseover', function(e){
				var liHovered = $(e.target);
				// if li > span
				if(!liHovered.is('li'))
					liHovered = liHovered.closest('li');

				if(liHovered.hasClass(hoverClass))
					return;

				panel.find('li.' + hoverClass).removeClass(hoverClass);
				liHovered.addClass(hoverClass);
			});
		};

		this.bindDelegateDocumentEvent = function(attrId){
			$(document).click(function(e){
				var target = $(e.target);
				if(!target.is('[data-pui-autocomplete]') && !target.is('[pui-autocomplete]')){
					$('.pui-autocomplete-panel').hide();

					// delete multiple choosed label
					// is a span <ul><li><span></span></li></ul>
					if(target.is('[data-pui-ac-close-span]')){
						var acId = target.attr('data-pui-ac-close-span');
						$('.pui-autocomplete-panel').each(function(){
							var panel = $(this);
							var panelAcId = panel.attr(attrId);
							if(acId === panelAcId){
								var targetVal = target.parent().attr('data-raw-value');
								panel.triggerHandler('puiAcDelVal', [targetVal]);
							}
						});

						target.parent().remove();
					}
				}else{
					// hide others panel
					var acId = target.attr(attrId);
					$('.pui-autocomplete-panel').each(function(){
						var panel = $(this);
						var panelAcId = panel.attr(attrId);
						if(acId !== panelAcId)
							panel.triggerHandler('puiAcHide');
					});
				}
			});
		};

		this.focusByCalIndex = function(panel, calFn){
			var hoverClass = 'ui-state-highlight';

			var liList = panel.find('li');
			var liCurrent = liList.filter('.' + hoverClass);
			liCurrent.removeClass(hoverClass);

			var index = liList.index(liCurrent);

			var targetIndex = calFn(index, liList.length);
			liList.eq(targetIndex).addClass(hoverClass);
		};

		this.focusPrev = function(panel){
			this.focusByCalIndex(panel, function(index, len){
				return index <= 0 ? len - 1 : index - 1;
			});
		};

		this.focusNext = function(panel){
			this.focusByCalIndex(panel, function(index, len){
				return index < len - 1 ? index + 1 : 0;
			});
		};

		this.wrapMultipleLi = function(targetVal, acId){
			return '<li data-raw-value="' + targetVal + 
				'" class="pui-autocomplete-token ui-state-active ui-corner-all ui-helper-hidden" ' + 
				'style="display: list-item;"><span data-pui-ac-close-span="' + acId + 
				'" class="pui-autocomplete-token-icon ui-icon ui-icon-close"></span>' + 
				'<span class="pui-autocomplete-token-label">' + targetVal + '</span></li>';
		};
	});

	md.filter('puiAutocompleteMatchedShow', function(){
		return function(str){
			return str;
		};
	});

	md.directive('puiAutocomplete', function($parse, $compile, puiAutocompleteHelper){
		var countNum = 0;
		var attrId = 'data-pui-ac-id';

		puiAutocompleteHelper.bindDelegateDocumentEvent(attrId);

		var defaultOptions = {
			height: 200, 
			multiple: false, 
			minChar: 1, 
			url: null
		};

		return {
			priority: 7001, 
			scope: {
				list: '='
			}, 
			require: 'ngModel', 
			transclude: true, 

			compile: function(el, attrs, transcludeFn){
				var multiple = !!attrs.multiple;

				return function(scope, el, attrs, ctrl){
					transcludeFn(scope, function(clone){
						if(multiple){
							el.addClass('pui-inputtext ui-widget ui-state-default ui-corner-all');
							el.wrap('<li class="pui-autocomplete-input-token"></li>');
							el.parent().wrap('<ul class="pui-autocomplete-multiple ui-widget pui-inputtext ui-state-default ui-corner-all"></ul>');
						}
					});
					var opts = scope.$eval(attrs.puiAutocomplete) || {};
					opts = angular.extend(angular.copy(defaultOptions), opts);
					console.log('Init puiAutocomplete 4 : ' + attrs.ngModel);
					console.log(opts);

					var cc = countNum++;
					el.attr(attrId, cc);

					var tpl = $('#pui-autocomplete-panel-tpl').html();
					var panelNg = $compile(tpl)(scope);
					var panel = $(panelNg[0]);
					panel.attr(attrId, cc);
					panel.appendTo($(document.body));

					panel.on('puiAcHide', function(e){
						e.preventDefault();
						e.stopPropagation();

						hidePanel();
					});

					if(multiple){
						panel.on('puiAcDelVal', function(e, targetVal){
							var targetValList = ctrl.$modelValue || [];
							var index = targetValList.indexOf(targetVal);
							if(index >= 0){
								targetValList.splice(index, 1);

								scope.$apply(function(){
									ctrl.$setViewValue(targetValList);
								});
							}
						});

						ctrl.$render = function(){
							var valList = ctrl.$modelValue || [];
							if(!valList.length)
								return;

							_.each(valList, function(targetVal){
								$(el[0]).parent().before(puiAutocompleteHelper.wrapMultipleLi(targetVal, cc));
							});
						};

						// multiple only accept array value
						ctrl.$parsers.unshift(function(value){
							return angular.isArray(value) ? value : ctrl.$modelValue;
						});
					}

					puiAutocompleteHelper.setPanelPosition(panel, $(el[0]), opts);
					puiAutocompleteHelper.bindPanelEvent(panel);

					panel.delegate('li', 'click', function(e){
						chooseCurrent($(e.target));
					});

					var chooseCurrent = function($li){
						panel.hide();

						if(!$li)
							$li = panel.find('li.ui-state-highlight');
						if(!$li.length)
							$li = panel.find('li').eq(0);
						if(!$li.length)
							return;

						var targetVal = $li.attr('data-raw-value');
						if(multiple){
							$(el[0]).parent().before(puiAutocompleteHelper.wrapMultipleLi(targetVal, cc));
							el.val('');

							var targetValList = ctrl.$modelValue || [];
							targetValList.push(targetVal);

							scope.$apply(function(){
								ctrl.$setViewValue(targetValList);
							});
						}else{
							el.val(targetVal);

							scope.$apply(function(){
								ctrl.$setViewValue(targetVal);
							});
						}
					};

					var checkIfNeedShow = function(val){
						return val.length >= opts.minChar;
					};

					var filterList = function(val){
						if(!scope.list)
							return [];

						return _.filter(scope.list, function(it){
							var isModelAlready = (!multiple && it === ctrl.$modelValue) || 
								(multiple && ctrl.$modelValue && ctrl.$modelValue.indexOf(it) >= 0);
							return it.indexOf(val) >= 0 && !isModelAlready;
						});
					};

					var isActive = false;
					var hidePanel = function(){
						panel.hide();
						isActive = false;
					};

					var showPanel = function(){
						panel.show();
						isActive = true;

						var val = el.val();
						var lastSearchVal = el.data('pui-autocomplete-search-val');

						if(val === lastSearchVal)
							return;

						el.data('pui-autocomplete-search-val', val);

						if(!checkIfNeedShow(val))
							return;

						scope.$apply(function(){
							scope.searchList = filterList(val);
						});
					};

					el.on('keydown', function(e){
						var keyCode = e.keyCode;
						// tab
						if(9 === keyCode){
							if(!isActive)
								return false;
							
							chooseCurrent();
						}
					});

					el.on('focus keyup', function(e){
						e.stopPropagation();

						var keyCode = e.keyCode;
						switch(keyCode){
							// up
							case 38: 
								if(!isActive)
									return false;
								
								puiAutocompleteHelper.focusPrev(panel);
								break;
							// down
							case 40: 
								if(!isActive)
									return false;
								
								puiAutocompleteHelper.focusNext(panel);
								break;
							// return
							case 13: 
								if(!isActive)
									return false;
								
								chooseCurrent();
								break;
							// esc
							case 27: 
								if(!isActive)
									return false;
								
								hidePanel();
								break;
							default:
								showPanel();
								break;
						}
					}); // end keyup
				}; // end return link
			}
		};
	});
	
	// ******************
	md.controller('MainCtrl', function($scope, $timeout){
		$scope.list = ['aaa', 'bbb', 'ccc', 'abc'];
		var i = 0;
		for(; i < 50; i++){
			$scope.list.push('aaa' + i);
		}

		$scope.ctrl = {
//			isGray: true
		};

		$scope.cc = ['aaa', 'bbb'];

//		$timeout(function(){
//			$scope.ctrl.isGray = false;
//		}, 1000 * 5);
	});

	angular.bootstrap(document, ['md']);
	</script>
	</body>
</html>